package hook

import (
	"fmt"
	jsoniter "github.com/json-iterator/go"
	"os/exec"
)

// Push 数据结构体
type Push struct {
	Ref                string     `json:"ref" description:"分支名"`
	Before             string     `json:"before" description:"上一次提交id"`
	After              string     `json:"after" description:"当前提交id"`
	TotalCommitsCount  int        `json:"total_commits_count" description:"提交文件数"`
	CommitsMoreThanTen bool       `json:"commits_more_than_ten" description:"提交总数是否大于12"`
	Created            bool       `json:"created" description:"推送是否为新分支"`
	Deleted            bool       `json:"deleted" description:"推送是否为删除分支"`
	Compare            string     `json:"compare" description:"推送差异查看地址"`
	Commits            []Commit   `json:"commits" description:"推送全部提交信息"`
	HeadCommit         Commit     `json:"head_commit" description:"推送最前面的提交信息"`
	Project            Project    `json:"project" description:"仓库信息"`
	Sender             User       `json:"sender" description:"推送者用户信息"`
	Enterprise         Enterprise `json:"enterprise" description:"仓库所在企业信息"`
	HookName           string     `json:"hook_name" description:"钩子名，固定为push_hooks/tag_push_hooks"`
	HookID             int64      `json:"hook_id" description:"钩子id"`
	HookURL            string     `json:"hook_url" description:"钩子详情"`
	Password           string     `json:"password" description:"钩子设置的密码"`
	Timestamp          string     `json:"timestamp" description:"时间戳"`
	Sign               string     `json:"sign" description:"根据秘钥计算的签名"`

	config 			*ProjectConf	`json:"-"`
	sellResult		[]byte			`json:"-"`
}

// 新的推送
func NewPush(groupName string, data []byte)(push *Push, err error){
	ok := false
	push = &Push{}
	if err = jsoniter.Unmarshal(data, push); err != nil{
		return nil, fmt.Errorf("接收数据解析错误:%w", err)
	}

	// 1.确定项目
	if push.config, ok = configs.HookGroup[groupName][push.Project.FullName]; !ok{
		return nil, ErrConfNot
	}

	// 1.2.测试推送，直接返回
	if push.Project.FullName == "oschina/git-osc" {
		push.sellResult = []byte(push.HeadCommit.Message)
		return push, nil
	}

	// 2.验证签名
	if err = push.CheckSign(); err != nil{
		return nil, err
	}

	// 3.执行动作
	push.sellResult = push.ActionSell()
	return push, nil
}

// 验证签名
func (m *Push)CheckSign()error{
	if m.config.Token == "false" { // 表示不验证密钥
		return nil
	}
	if m.config.Token != m.Password{
		return ErrToken
	}
	return nil
}

// 执行sell 命令
func (m *Push)ActionSell()[]byte{
	if m.config.Event.Push.Sell == "" {
		return nil
	}
	//var out bytes.Buffer
	//var stderr bytes.Buffer

	cmd := exec.Command("bash", "-c", m.config.Event.Push.Sell)
	//cmd.Stdout = &out
	//cmd.Stderr =  &stderr
	//
	//err := cmd.Run()
	//if err != nil {
	//	return  []byte("error:"+ fmt.Sprint(err) + ":" + stderr.String())
	//}else {
	//	return []byte(out.String()+"|" + stderr.String())
	//}

	// 这里的问题是，在错误的时候，不会返回详情。
	b, err := cmd.CombinedOutput()
	if  err != nil{
		return []byte("error:"+ err.Error())
	}
	//默认输出有一个换行
	return b
}

func (m *Push)GetSellResult()[]byte{
	return m.sellResult
}